package main

import (
	"bytes"
	"container/list"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

//实现json序列化/反序列化对map的支持

type User struct {
	Name string
	Age  int
	Sex  byte `json:"gender"`
}

type Book struct {
	ISBN     string `json:"isbn"`
	Title    string
	Author   *User    `json:"author"`
	Price    float32  `json:"price"`
	KeyWords []string `json:"kws"`
	Local    map[int]bool
}

/*
适用于嵌套结构体的序列化字符串分割
*/
func SpiltJson(json string) []string {
	rect := make([]string, 0, 10)
	stack := list.New()
	beginIndex := 0
	for i, ch := range json {
		if ch == rune('{') || ch == rune('[') {
			stack.PushBack(struct{}{})
		} else if ch == rune('}') || ch == rune(']') {
			ele := stack.Back()
			if ele != nil {
				stack.Remove(ele)
			}
		} else if ch == rune(',') {
			if stack.Len() == 0 {
				rect = append(rect, json[beginIndex:i])
				beginIndex = i + 1
			}
		}
	}

	rect = append(rect, json[beginIndex:])
	return rect
}

func Marshal(v interface{}) ([]byte, error) {
	value := reflect.ValueOf(v)
	form := reflect.TypeOf(v)
	if form.Kind() == reflect.Ptr {
		if value.IsNil() {
			return []byte("null"), nil
		} else {
			value = value.Elem()
			form = form.Elem()
		}
	}

	rbuf := bytes.Buffer{}
	switch form.Kind() {
	case reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64,
		reflect.Int,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uint:
		return []byte(fmt.Sprintf("%v", value.Interface())), nil
	case reflect.Float32,
		reflect.Float64:
		return []byte(fmt.Sprintf("%f", value.Float())), nil
	case reflect.String:
		return []byte(fmt.Sprintf("\"%s\"", value.String())), nil
	case reflect.Bool:
		return []byte(fmt.Sprintf("%t", value.Bool())), nil
	case reflect.Struct:
		rbuf.WriteByte('{')
		if value.NumField() > 0 {
			for i := 0; i < value.NumField(); i++ {
				fieldValue := value.Field(i)
				fieldType := form.Field(i)
				if fieldType.IsExported() {
					name := fieldType.Name
					if len(fieldType.Tag.Get("json")) > 0 {
						name = fieldType.Tag.Get("json")
					}
					rbuf.WriteString("\"")
					rbuf.WriteString(name)
					rbuf.WriteString("\"")
					rbuf.WriteString(":")
					if bs, err := Marshal(fieldValue.Interface()); err != nil {
						return nil, err
					} else {
						rbuf.Write(bs)
					}
					rbuf.WriteString(",")
				}
			}
			rbuf.Truncate(len(rbuf.Bytes()) - 1)
		}
		rbuf.WriteByte('}')
		return rbuf.Bytes(), nil
	case reflect.Slice:
		//判断是否持有值，且是否为空
		if value.IsValid() && value.IsNil() {
			return []byte("null"), nil
		}
		rbuf.WriteByte('[')
		if value.Len() > 0 {
			for i := 0; i < value.Len(); i++ {
				if bs, err := Marshal(value.Index(i).Interface()); err != nil {
					return nil, err
				} else {
					rbuf.Write(bs)
					rbuf.WriteString(",")
				}
			}
			rbuf.Truncate(len(rbuf.Bytes()) - 1)
		}
		rbuf.WriteByte(']')
		return rbuf.Bytes(), nil
	case reflect.Map:
		//判断是否持有值，且是否为空
		if value.IsValid() && value.IsNil() {
			return []byte("null"), nil
		}
		rbuf.WriteByte('{')
		if value.Len() > 0 {
			for _, key := range value.MapKeys() {
				if keyBs, err := Marshal(key.Interface()); err != nil {
					return nil, err
				} else {
					rbuf.Write(keyBs)
					rbuf.WriteString(":")
					para := value.MapIndex(key)
					if valBs, err := Marshal(para.Interface()); err != nil {
						return nil, err
					} else {
						rbuf.Write(valBs)
						rbuf.WriteString(",")
					}
				}
			}
			rbuf.Truncate(len(rbuf.Bytes()) - 1)
		}
		rbuf.WriteByte('}')
		return rbuf.Bytes(), nil
	default:
		return []byte(nil), fmt.Errorf("暂不支持该类型 %s", form.Kind().String())
	}
}

func UnMarshal(v interface{}, data []byte) error {
	str := string(data)
	//去除前后空格
	str = strings.TrimLeft(str, " ")
	str = strings.TrimRight(str, " ")
	form := reflect.TypeOf(v)
	value := reflect.ValueOf(v)
	if form.Kind() != reflect.Ptr {
		return errors.New("must pass pointer parameter")
	}

	form = form.Elem()
	value = value.Elem()

	switch form.Kind() {
	case reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64,
		reflect.Int:
		if i, err := strconv.ParseInt(str, 10, 64); err != nil {
			return err
		} else {
			value.SetInt(i) //有符号整型通过SetInt
		}
	case reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uint:
		if i, err := strconv.ParseUint(str, 10, 64); err != nil {
			return err
		} else {
			value.SetUint(i) //无符号整型通过SetUint
		}
	case reflect.Float32,
		reflect.Float64:
		if f, err := strconv.ParseFloat(str, 64); err != nil {
			return err
		} else {
			value.SetFloat(f) //通过reflect.Value修改原始数据的值
		}
	case reflect.String:
		if str[0] == '"' && str[len(str)-1] == '"' {
			value.SetString(str[1 : len(str)-1]) //去除前后的""
		} else {
			// return errors.New(fmt.Sprintf("invalid json part: %s", str))
			return fmt.Errorf("invalid json part: %s", str)
		}
	case reflect.Bool:
		if b, err := strconv.ParseBool(str); err == nil {
			value.SetBool(b)
		} else {
			return err
		}
	case reflect.Struct:
		if str[0] == '{' && str[len(str)-1] == '}' {
			arr := SpiltJson(str[1 : len(str)-1])
			if len(arr) > 0 {
				fieldCount := form.NumField()
				//建立json tag到FieldName的映射关系
				tag2Field := make(map[string]string, fieldCount)
				for i := 0; i < fieldCount; i++ {
					fieldType := form.Field(i)
					name := fieldType.Name
					if len(fieldType.Tag.Get("json")) > 0 {
						name = fieldType.Tag.Get("json")
					}
					tag2Field[name] = fieldType.Name
				}

				for _, ele := range arr {
					brr := strings.SplitN(ele, ":", 2) //json的value里可能存在嵌套，所以用:分隔时限定个数为2
					if len(brr) == 2 {
						tag := strings.Trim(brr[0], " ")
						if tag[0] == '"' && tag[len(tag)-1] == '"' {
							tag = tag[1 : len(tag)-1]
							if fieldName, exists := tag2Field[tag]; exists {
								fieldValue := value.FieldByName(fieldName)
								fieldType := fieldValue.Type()
								if fieldType.Kind() != reflect.Ptr {
									fieldValue = fieldValue.Addr()
									if err := UnMarshal(fieldValue.Interface(), []byte(brr[1])); err != nil {
										return err
									}
								} else {
									newValue := reflect.New(fieldType.Elem())
									if err := UnMarshal(newValue.Interface(), []byte(brr[1])); err != nil {
										return err
									}
									value.FieldByName(fieldName).Set(newValue)
								}
							} else {
								return fmt.Errorf("字段找不到 %s", tag)
							}
						} else {
							return fmt.Errorf("invalid json part: %s", tag)
						}
					} else {
						return fmt.Errorf("invalid json part: %s", ele)
					}
				}
			}
		} else if str != "null" {
			return fmt.Errorf("invalid json part: %s", str)
		}
	case reflect.Slice:
		if str[0] == '[' && str[len(str)-1] == ']' {
			arr := SpiltJson(str[1 : len(str)-1])
			if len(arr) > 0 {
				slice := reflect.ValueOf(v).Elem()                     //传入是一个指针，所以这里要解析
				slice.Set(reflect.MakeSlice(form, len(arr), len(arr))) //通过反射创建实例
				for i := 0; i < len(arr); i++ {
					eleValue := slice.Index(i)
					eleType := eleValue.Type()
					if eleType.Kind() != reflect.Ptr {
						eleValue = eleValue.Addr()
					}
					if err := UnMarshal(eleValue.Interface(), []byte(arr[i])); err != nil {
						return err
					}
				}
			}
		} else if str != "null" {
			return fmt.Errorf("invalid json part: %s", str)
		}
	case reflect.Map:
		if str[0] == '{' && str[len(str)-1] == '}' {
			arr := SpiltJson(str[1 : len(str)-1])
			if len(arr) > 0 {
				mapValue := reflect.ValueOf(v).Elem()
				mapValue.Set(reflect.MakeMapWithSize(form, len(arr)))

				kType := form.Key()
				vType := form.Elem()
				for i := 0; i < len(arr); i++ {
					brr := strings.Split(arr[i], ":")
					if len(brr) != 2 {
						return fmt.Errorf("invalid json part: %s", arr[i])
					}

					kValue := reflect.New(kType)
					if err := UnMarshal(kValue.Interface(), []byte(brr[0])); err != nil {
						return err
					}
					vValue := reflect.New(vType)
					if err := UnMarshal(vValue.Interface(), []byte(brr[1])); err != nil {
						return err
					}
					mapValue.SetMapIndex(kValue.Elem(), vValue.Elem())
				}
			}
		} else if str != "null" {
			return fmt.Errorf("invalid json part: %s", str)
		}
	default:
		return fmt.Errorf("暂不支持此类型:%s", form.Kind().String())
	}

	return nil
}

func main() {
	user := User{
		Name: "余华",
		Age:  62,
		Sex:  1,
	}

	book := Book{
		ISBN:     "568155567",
		Title:    "活着",
		Price:    40.0,
		Author:   &user,                      //改成nil试试
		KeyWords: []string{"舍得", "命运", "坎坷"}, //把这一行注释掉试一下，测测null
		Local:    map[int]bool{1: true, 3: false},
	}

	if bytes, err := Marshal(user); err != nil { //也可以给Marshal传指针类型
		fmt.Printf("序列化失败: %v\n", err)
	} else {
		fmt.Println(string(bytes))
		var u User
		if err = UnMarshal(&u, bytes); err != nil {
			fmt.Printf("反序列化失败: %v\n", err)
		} else {
			fmt.Printf("user name %s\n", u.Name)
		}
	}

	if bytes, err := json.Marshal(user); err != nil {
		fmt.Printf("序列化失败: %v\n", err)
	} else {
		fmt.Println(string(bytes))
		var u User
		if err = json.Unmarshal(bytes, &u); err != nil {
			fmt.Printf("反序列化失败: %v\n", err)
		} else {
			fmt.Printf("user name %s\n", u.Name)
		}
	}

	if bytes, err := Marshal(book); err != nil { //也可以给Marshal传指针类型
		fmt.Printf("序列化失败: %v\n", err)
	} else {
		fmt.Println(string(bytes))
		var b Book //必须先声明值类型，再通过&给Unmarshal传一个指针参数。因为声明值类型会初始化为0值，而声明指针都没有创建底层的内存空间
		if err = UnMarshal(&b, bytes); err != nil {
			fmt.Printf("反序列化失败: %v\n", err)
		} else {
			fmt.Printf("book name %s author name %s local %v\n", b.Title, b.Author.Name, b.Local)
		}
	}

	if bytes, err := json.Marshal(book); err != nil {
		fmt.Printf("序列化失败: %v\n", err)
	} else {
		fmt.Println(string(bytes))
		var b Book
		if err = json.Unmarshal(bytes, &b); err != nil {
			fmt.Printf("反序列化失败: %v\n", err)
		} else {
			fmt.Printf("book name %s author name %s local %v\n", b.Title, b.Author.Name, b.Local)
		}
	}
}
